/**
 * COPYRIGHT (C) 2009. Denny Tran, Omar Jaime, David Deng, Julie Hsieh. All Rights Reserved
 * Class is a ViewPanel containing JComponents asking for event information.  
 * @author Denny Tran, Omar Jaime, David Deng, Julie Hsieh 
 * @version 1.01 2009-05-05
 */

package gui;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import data.Event;
import data.Group;
import data.GroupSystem;
import data.MyCalendar;
import data.User;

import javax.swing.*;

public class AddEvent extends ViewPanel
{
    private String[] months = { "January", "February", "March", "April", "May", "June", "July", "August", "October",
            "September", "November", "December" };
    private Integer[] days = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};
    private Integer[] years = {2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020};
    private Integer[] hours = {12,1,2,3,4,5,6,7,8,9,10,11};
    private String[] minutes = {"00", "15", "30", "45"}; // using string so the text is formatted the way we want
    private String[] ampm = {"AM", "PM"};
    
    private Event currentEvent; // used to get the current event for this panel, null if adding event
    
    private JLabel title;
    private JLabel type;
    private JRadioButton single;
    private JRadioButton group;
    private ButtonGroup typeGroup;
    private JLabel nameLabel;
    private JLabel recursiveLabel;
    private JLabel descLabel;
    private JTextField nameField;
    private JCheckBox sunCheck;
    private JCheckBox monCheck;
    private JCheckBox tueCheck;
    private JCheckBox wedCheck;
    private JCheckBox thuCheck;
    private JCheckBox friCheck;
    private JCheckBox satCheck;
    private JCheckBox[] checkboxes;
    private JTextArea descField;
    private JButton confirmButton;
    private JButton cancelButton;
    private JLabel meetingLabel;
    private JLabel startTimeLabel;
    private JLabel endTimeLabel;
    private JComboBox startmonthBox;
    private JComboBox startdayBox;
    private JComboBox startyearBox;
    private JComboBox startHrBox;
    private JComboBox startMinBox;
    private JComboBox startAMPMBox;
    private JComboBox endHrBox;
    private JComboBox endMinBox;
    private JComboBox endAMPMBox;
    private JButton deleteButton;
    
    private static int tempid;
    
    /**
     * Construct ViewPanel containing JComponents asking for event information
     * @param viewManager the container of this panel
     * @param identification specific identification used to reference this panel
     */
    public AddEvent(final ViewManager viewManager, String identification)
    {
        super(viewManager, identification);
        tempid = 200000;
        
        Dimension labelSize = new Dimension(80, 20);
        int labelX = 60;
        int labelY = 40;
        int labelSpread = 30;
        
        // labels
        title = new JLabel("Add Event");
        title.setFont(new Font("Serif", Font.PLAIN, 24));
        title.setSize(150, 30);
        title.setLocation(60, 0);
        this.add(title);
        
        //labels
        type = new JLabel("Event Type: ");
        type.setSize(labelSize);
        type.setLocation(labelX, labelY);
        labelY += labelSpread;
        this.add(type);
        
        nameLabel = new JLabel("Name:");
        nameLabel.setSize(labelSize);
        nameLabel.setLocation(labelX,labelY);
        labelY += labelSpread;
        this.add(nameLabel);
    
        meetingLabel = new JLabel("Meeting Date: ");
        meetingLabel.setSize(labelSize);
        meetingLabel.setLocation(labelX, labelY);
        labelY += labelSpread;
        this.add(meetingLabel);      
        
        startTimeLabel = new JLabel("Start Time: ");
        startTimeLabel.setSize(labelSize);
        startTimeLabel.setLocation(labelX, labelY);
        labelY += labelSpread;
        this.add(startTimeLabel);
        
        endTimeLabel = new JLabel("End Time: ");
        endTimeLabel.setSize(labelSize);
        endTimeLabel.setLocation(labelX, labelY);
        labelY += labelSpread;
        this.add(endTimeLabel);
        
        recursiveLabel = new JLabel("Every: ");
        recursiveLabel.setSize(labelSize);
        recursiveLabel.setLocation(labelX, labelY);
        labelY += labelSpread;
        labelY += labelSpread;
        this.add(recursiveLabel);
        
        descLabel = new JLabel("Description: ");
        descLabel.setSize(labelSize);
        descLabel.setLocation(labelX, labelY);
        labelY += labelSpread;
        this.add(descLabel);
        
        // text fields
        Dimension textFieldSize = new Dimension(150,20);
        int textFieldX = labelX + (int)labelSize.getWidth() + 20;
        int textFieldY = 40;
        // use same spread as labels
        
        //radio buttons     
        single = new JRadioButton("Individual", true);
        single.setActionCommand("single");
        single.setSize(labelSize);
        single.setLocation(textFieldX, textFieldY);
        group = new JRadioButton("Group");
        group.setActionCommand("group");
        group.setSize(labelSize);
        group.setLocation(textFieldX + 80, textFieldY);
        //create a button group for the radio buttons
        typeGroup = new ButtonGroup();
        typeGroup.add(single);
        typeGroup.add(group);
        textFieldY += labelSpread;
        this.add(group);
        this.add(single);
        //String cipherType = cipherTypeGroup.getSelection().getActionCommand();
        
        nameField = new JTextField();
        nameField.setSize(textFieldSize);
        nameField.setLocation(textFieldX, textFieldY);
        textFieldY += labelSpread;
        this.add(nameField);
            
      //start date
        startmonthBox = new JComboBox(months);
        startmonthBox.setSelectedIndex(3);
        startmonthBox.setSize(90, 20);
        startmonthBox.setLocation(textFieldX, textFieldY);
        startdayBox = new JComboBox(days);
        startdayBox.setSelectedIndex(21);   
        startdayBox.setSize(50, 20);
        startdayBox.setLocation(textFieldX + 90, textFieldY);
        startyearBox = new JComboBox(years);
        startyearBox.setSize(60, 20);
        startyearBox.setLocation(textFieldX + 140, textFieldY);
        textFieldY += labelSpread;
        this.add(startmonthBox);
        this.add(startdayBox);
        this.add(startyearBox);
        
        //start time
        startHrBox = new JComboBox(hours);
        startHrBox.setSelectedIndex(11);
        startHrBox.setSize(90, 20);
        startHrBox.setLocation(textFieldX, textFieldY);
        startMinBox = new JComboBox(minutes);   
        startMinBox.setSize(50, 20);
        startMinBox.setLocation(textFieldX + 90, textFieldY);
        startAMPMBox = new JComboBox(ampm);
        startAMPMBox.setSize(60, 20);
        startAMPMBox.setLocation(textFieldX + 140, textFieldY);
        textFieldY += labelSpread;
        this.add(startHrBox);
        this.add(startMinBox);
        this.add(startAMPMBox);
        
      //end time
        endHrBox = new JComboBox(hours);
        endHrBox.setSelectedIndex(11);
        endHrBox.setSize(90, 20);
        endHrBox.setLocation(textFieldX, textFieldY);
        endMinBox = new JComboBox(minutes);
        endMinBox.setSize(50, 20);
        endMinBox.setLocation(textFieldX + 90, textFieldY);
        endAMPMBox = new JComboBox(ampm);
        endAMPMBox.setSize(60, 20);
        endAMPMBox.setLocation(textFieldX + 140, textFieldY);
        textFieldY += labelSpread;
        this.add(endHrBox);
        this.add(endMinBox);
        this.add(endAMPMBox);
        
      //check-boxes
        sunCheck = new JCheckBox("Sunday"); 
        sunCheck.setSelected(false);
        sunCheck.setLocation(textFieldX, textFieldY);
        sunCheck.setSize(80, 20);
        monCheck = new JCheckBox("Monday"); 
        monCheck.setSelected(false);
        monCheck.setLocation(textFieldX + 80, textFieldY);
        monCheck.setSize(80, 20);
        tueCheck = new JCheckBox("Tuesday"); 
        tueCheck.setSelected(false);
        tueCheck.setLocation(textFieldX + 160, textFieldY);
        tueCheck.setSize(80, 20);
        wedCheck = new JCheckBox("Wednesday"); 
        wedCheck.setSelected(false);
        wedCheck.setLocation(textFieldX + 240, textFieldY);
        wedCheck.setSize(100, 20);
        textFieldY += labelSpread;
        thuCheck = new JCheckBox("Thursday"); 
        thuCheck.setSelected(false);
        thuCheck.setLocation(textFieldX, textFieldY);
        thuCheck.setSize(80, 20);
        friCheck = new JCheckBox("Friday"); 
        friCheck.setSelected(false);
        friCheck.setLocation(textFieldX + 80, textFieldY);
        friCheck.setSize(80, 20);
        satCheck = new JCheckBox("Saturday"); 
        satCheck.setSelected(false);
        satCheck.setLocation(textFieldX + 160, textFieldY);
        satCheck.setSize(80, 20);
        textFieldY += labelSpread;
        checkboxes = new JCheckBox[7];
        checkboxes[0] = sunCheck;
        checkboxes[1] = monCheck;
        checkboxes[2] = tueCheck;
        checkboxes[3] = wedCheck;
        checkboxes[4] = thuCheck;
        checkboxes[5] = friCheck;
        checkboxes[6] = satCheck;
        this.add(sunCheck);
        this.add(monCheck);
        this.add(tueCheck);
        this.add(wedCheck);
        this.add(thuCheck);
        this.add(friCheck);
        this.add(satCheck);

        
        //description        
        descField = new JTextArea();        
        JScrollPane descPanel = new JScrollPane(descField);
        descPanel.setSize(350,120);
        descPanel.setLocation(textFieldX, textFieldY);
        this.add(descPanel);
        
        //buttons        
        confirmButton = new JButton("Save");
        confirmButton.setSize(80,20);
        confirmButton.setLocation(100, 390);
        confirmButton.addActionListener(new ActionListener()
        {
			public void actionPerformed(ActionEvent arg0)
			{
			    String name = nameField.getText();
			    if (name.isEmpty())
			    {
			        JOptionPane.showMessageDialog(null, "Name field is empty.");
			        return;
			    }
			    int year = (Integer) startyearBox.getSelectedItem();
			    int month = startmonthBox.getSelectedIndex();
			    int day = (Integer) startdayBox.getSelectedItem();
			    
			    int startHour = startHrBox.getSelectedIndex() + (startAMPMBox.getSelectedItem().equals("PM") ? 12 : 0);
			    int startMinute = Integer.parseInt((String)startMinBox.getSelectedItem());
			    int endHour = endHrBox.getSelectedIndex() + (endAMPMBox.getSelectedItem().equals("PM") ? 12 : 0);
			    int endMinute = Integer.parseInt((String)endMinBox.getSelectedItem());
			    
			    GregorianCalendar start = new GregorianCalendar(year, month, day, startHour, startMinute);
			    GregorianCalendar end = new GregorianCalendar(year, month, day, endHour, endMinute);
			    
			    if (start.compareTo(end) >= 0)
			    {
			        JOptionPane.showMessageDialog(null, "End time must be after start time.");
			        return;
			    }
			    
			    boolean[] recurrence = new boolean[8]; // 8 because get day from calendar returns 1-7
			    int index = 1;
			    for (JCheckBox box : checkboxes)
			        recurrence[index++] = box.isSelected();
			    
			    String desc = descField.getText();
			    
                String type = typeGroup.getSelection().getActionCommand();
			    String userName = "";
			    if (type.equals("single"))
			        userName = viewManager.getGs().getUser().getUserName();
			    
			    Event event = new Event(tempid++, name, viewManager.getGs().getGroup().getGroupID(), userName, "event", start, end, desc);
			    event.setRecurrence(recurrence, "event");
                if (currentEvent == null) // adding event
                {
                    boolean added = false;
                    
                    if (type.equals("single"))
                    {
                        event.setUserName(viewManager.getGs().getUser().getUserName());
                        System.out.println("Adding single user event here:");
                        System.out.println("User = " + viewManager.getGs().getUser().getUserName());
                        System.out.println("RealName = " + viewManager.getGs().getUser().getRealName());
                        System.out.println("Calendar = " + viewManager.getGs().getUser().getUserCalendar());
                        
                        added = viewManager.getGs().getUser().getUserCalendar().addEvent(event);
                    }
                    else if (type.equals("group"))
                    {
                        added = viewManager.getGs().getGroup().getGroupCalendar().addEvent(event);
                    }
                    else
                        System.out.println("error invalid type, should be single or group: " + type);
    
                    if (!added)
                    {
                        JOptionPane.showMessageDialog(null, "Could not add because of time conflict.");
                        return;
                    }
                    else
                    {
                       try
                       {
                          //Adding event
                          viewManager.getGs().getMySql().addEvent(event);
                          System.out.println("Adding:" + event);
                       }
                       catch(SQLException e)
                       {
                          System.out.println("No MySql set up yet.");
                       }
                    }
                }
                else // editing event
                {
                    MyCalendar cal = null;
                    Event checkEvent = null;
                    if (type.equals("single"))
                    {
                        cal = viewManager.getGs().getUser().getUserCalendar();
                        checkEvent = cal.getEvent(currentEvent.getEventID());
                    }
                    else if (type.equals("group"))
                    {
                        cal = viewManager.getGs().getGroup().getGroupCalendar();
                        checkEvent = cal.getEvent(currentEvent.getEventID());
                    }
                    else
                        System.out.println("error invalid type, should be single or group: " + type);
                    
                    if(checkEvent.isRecurring())
                    {
                        int orgYear = checkEvent.getStartTime().get(Calendar.YEAR);
                        int orgMonth = checkEvent.getStartTime().get(Calendar.MONTH);
                        int orgDay = checkEvent.getStartTime().get(Calendar.DATE);
                        
                        event.getStartTime().set(Calendar.YEAR,orgYear);
                        event.getStartTime().set(Calendar.MONTH,orgMonth);
                        event.getStartTime().set(Calendar.DATE,orgDay);
                        event.getEndTime().set(Calendar.YEAR,orgYear);
                        event.getEndTime().set(Calendar.MONTH,orgMonth);
                        event.getEndTime().set(Calendar.DATE,orgDay);
                    }
                    
                    boolean edited = cal.editEvent(currentEvent.getEventID(), event);
                    if (!edited)
                    {
                        JOptionPane.showMessageDialog(null, "Could not edit because of time conflict.");
                        return;
                    }
                    else
                    {
                       try
                       {
                          //Editing event
                          //remove the old event
                          viewManager.getGs().getMySql().removeEvent(currentEvent.getEventID());
                          //add in a new event
                          viewManager.getGs().getMySql().addEvent(event);
                          System.out.println("Adding:" + event);
                       }
                       catch(SQLException e)
                       {
                          System.out.println("No MySql set up yet.");
                       }
                    }
                }
                JOptionPane.showMessageDialog(null, event.getEventName() + " added.");
                CalendarPanel cal = (CalendarPanel)viewManager.getView("calendar");
                
                // move view to new event's date
                if (!event.isRecurring())
                    cal.setCurrent((GregorianCalendar)event.getStartTime().clone());
                
                if (type.equals("group"))
                    index = 0;
                else
                {
                    User u = viewManager.getGs().getUser();
                    index = viewManager.getGs().getGroup().getUsers().indexOf(u) + 1;
                }
                cal.getTabPanel().setSelectedIndex(index);
                
                cal.reload();
                viewManager.showView("calendar");
			}        	
        });
        this.add(confirmButton);
        
        deleteButton = new JButton("Delete");
        deleteButton.setSize(80,20);
        deleteButton.setLocation(200, 390);
        deleteButton.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(ActionEvent e)
            {
                boolean deleted = false;
                Group g = viewManager.getGs().getGroup(); 
                
                if (currentEvent.getUserName().isEmpty()) // group event
                    deleted = g.getGroupCalendar().removeEvent(currentEvent.getEventID());
                else
                    deleted = g.getUser(currentEvent.getUserName()).getUserCalendar().removeEvent(currentEvent.getEventID());
                
                if (!deleted)
                {
                    JOptionPane.showMessageDialog(null, "Event was not deleted.");
                    return;
                }
                else
                {
                   try
                   {
                      //Deleting event
                      //remove the old event
                      viewManager.getGs().getMySql().removeEvent(currentEvent.getEventID());
                   }
                   catch(SQLException se)
                   {
                      System.out.println("No MySql set up yet.");
                   }
                }
                
                JOptionPane.showMessageDialog(null, currentEvent.getEventName() + " is now deleted.");
                viewManager.showView("calendar");
                
                CalendarPanel cal = (CalendarPanel)viewManager.getView("calendar");
                cal.reload();
            }
            
        });
        this.add(deleteButton);
        
        cancelButton = new JButton("Cancel");
        cancelButton.setSize(80,20);
        cancelButton.setLocation(300, 390);
        cancelButton.addActionListener(viewManager.addLink("calendar"));
        this.add(cancelButton);
    }
    
    /**
     * Clears all text fields and check boxes
     */
    public void clearView()
    {
        this.title.setText("Add Event");
        nameField.setText("");
        startmonthBox.setSelectedIndex(0);
        startdayBox.setSelectedIndex(0);
        startyearBox.setSelectedIndex(0);
        startHrBox.setSelectedIndex(0);
        startMinBox.setSelectedIndex(0);
        startAMPMBox.setSelectedIndex(0);
        endHrBox.setSelectedIndex(0);
        endMinBox.setSelectedIndex(0);
        endAMPMBox.setSelectedIndex(0);
        
        for(JCheckBox checkbox : checkboxes)
            checkbox.setSelected(false);
        
        descField.setText("");
        currentEvent = null;
        deleteButton.setVisible(false); // default to invisible
    }
    
    /**
     * Sets text fields to display the event's information
     * @param e the event whose information is shown
     */
    public void setView(Event e)
    {
        if (e.getUserName().isEmpty())
           group.setSelected(true);
        else
           single.setSelected(true);
        this.title.setText("Edit Event");
        GregorianCalendar start = e.getStartTime();
        GregorianCalendar end = e.getEndTime();
        nameField.setText(e.getEventName());
        startmonthBox.setSelectedIndex(start.get(Calendar.MONTH));
        startdayBox.setSelectedIndex(indexOf(days, start.get(Calendar.DAY_OF_MONTH)));
        startyearBox.setSelectedIndex(indexOf(years, start.get(Calendar.YEAR)));
        startHrBox.setSelectedIndex(start.get(Calendar.HOUR));
        startMinBox.setSelectedIndex(indexOf(minutes, String.format("%02d", start.get(Calendar.MINUTE))));
        startAMPMBox.setSelectedIndex(start.get(Calendar.AM_PM));
        endHrBox.setSelectedIndex(indexOf(hours, end.get(Calendar.HOUR)));
        endMinBox.setSelectedIndex(indexOf(minutes, String.format("%02d", end.get(Calendar.MINUTE))));
        endAMPMBox.setSelectedIndex(end.get(Calendar.AM_PM));
        
        boolean[] recurrence = e.getDaysOfWeek();
        for (int i = 1 ; i < recurrence.length; i++)
            checkboxes[i-1].setSelected(recurrence[i]);
        
        descField.setText(e.getDescription());
        deleteButton.setVisible(true);
        currentEvent = e;
    }
    
    /**
     * Returns the in of specified element in an array.
     * @param array the arrays where element is searched in.
     * @param element the element to be found in array
     * @return index of the element in the array
     */
    private <E> int indexOf(E[] array, E element)
    {
        int i = 0;
        for (E obj : array)
        {
            if (obj.equals(element))
                return i;
            i++;
        }
        return -1;
    }

    /**
     * Returns the current event in the class
     * @return the current event
     */
    public Event getCurrentEvent()
    {
        return currentEvent;
    }

    /**
     * Sets the current event to the parameter event
     * @param currentEvent the new value of current event
     */
    public void setCurrentEvent(Event currentEvent)
    {
        this.currentEvent = currentEvent;
    }
}